//
//  UtilManager.swift
//  TalkeApp
//
//  Created by lhf on 2024/3/8.
//

import Foundation
import Alamofire
import SwiftyJSON
import MJRefresh
import SwiftyUserDefaults
import MBProgressHUD
import AVFoundation
import Photos

private let utilManager = UtilManager()

class UtilManager: NSObject {
    
    //单例
    class var sharedInstance: UtilManager {
        return utilManager
    }
    
    //获取屏幕宽度
    func getScreenWidth() -> CGFloat {
        
        return UIScreen.main.bounds.size.width
    }
    
    //获取屏幕高度
    func getScreenHeight() -> CGFloat {
        return UIScreen.main.bounds.size.height
    }
    
    //获取跟控制器
    func getRootVc() -> UIViewController {
        let foregroundActiveList = UIApplication.shared.connectedScenes.filter { $0.activationState == .foregroundActive }
        if foregroundActiveList.count != 0 {
            let keyWindow = UIApplication.shared.connectedScenes
            // Keep only active scenes, onscreen and visible to the user
            .filter { $0.activationState == .foregroundActive }
            // Keep only the first `UIWindowScene`
            .first(where: { $0 is UIWindowScene })
            // Get its associated windows
            .flatMap({ $0 as? UIWindowScene })?.windows
            // Finally, keep only the key window
            .first(where: \.isKeyWindow)
            
            return (keyWindow?.rootViewController!)!
        }
        
        let foregroundInactiveList = UIApplication.shared.connectedScenes.filter { $0.activationState == .foregroundInactive }
        if foregroundInactiveList.count != 0 {
            let keyWindow = UIApplication.shared.connectedScenes
            // Keep only active scenes, onscreen and visible to the user
            .filter { $0.activationState == .foregroundInactive }
            // Keep only the first `UIWindowScene`
            .first(where: { $0 is UIWindowScene })
            // Get its associated windows
            .flatMap({ $0 as? UIWindowScene })?.windows
            // Finally, keep only the key window
            .first(where: \.isKeyWindow)
            
            return (keyWindow?.rootViewController!)!
        }
        
        return UIViewController()
        
    }
    
    //将图片从中间裁剪成指定比例（多余部分自动删除）
    func cropImage(image: UIImage ,ratio: CGFloat) -> UIImage {
        //计算最终尺寸
        var newSize:CGSize!
        if image.size.width / image.size.height > ratio {
            newSize = CGSize(width: image.size.height * ratio, height: image.size.height)
        }else{
            newSize = CGSize(width: image.size.width, height: image.size.width / ratio)
        }
     
        ////图片绘制区域
        var rect = CGRect.zero
        rect.size.width  = image.size.width
        rect.size.height = image.size.height
        rect.origin.x    = (newSize.width - image.size.width ) / 2.0
        rect.origin.y    = (newSize.height - image.size.height ) / 2.0
         
        //绘制并获取最终图片
        UIGraphicsBeginImageContext(newSize)
        image.draw(in: rect)
        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
         
        return scaledImage!
    }
    
    // 重设图片大小
    func reSizeImage(reSize:CGSize,image:UIImage)->UIImage {
        UIGraphicsBeginImageContext(reSize)
        UIGraphicsBeginImageContextWithOptions(reSize,false,UIScreen.main.scale)
        image.draw(in: CGRect.init(x: 0, y: 0, width: reSize.width, height: reSize.height))
        let reSizeImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext();
        return reSizeImage;
    }
    
    // 颜色转图片
    func creatImageWithColor(color: UIColor)->UIImage{
        let rect = CGRect(x:0,y:0,width:1,height:1)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()
        context?.setFillColor(color.cgColor)
        context!.fill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image!
    }

    // 两张图片合并
    func composeImg(topImg: UIImage, bottomImg: UIImage,topSize: CGSize,bottomSize: CGSize) -> UIImage {
        
        //以bottomImg的图大小为画布创建上下文
        UIGraphicsBeginImageContext(CGSize(width: bottomSize.width, height: bottomSize.height))
        bottomImg.draw(in: CGRect(x: 0, y: 0, width: bottomSize.width, height: bottomSize.height))
        topImg.draw(in: CGRect(x: (bottomSize.width - topSize.width) / 2, y: (bottomSize.height - topSize.height) / 2, width: topSize.width, height: topSize.height))
        let resultImg = UIGraphicsGetImageFromCurrentImageContext() //从当前上下文中获得最终图片
        UIGraphicsEndImageContext() //关闭上下文

        let path = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).map(\.path).last
        let filePath = URL(fileURLWithPath: path ?? "").appendingPathComponent("01.png").path
        if let img2 = resultImg?.pngData() {
            NSData(data: img2).write(toFile: filePath, atomically: true)
        } //保存图片到沙盒
        
        return resultImg!
    }
    
    // 等比率缩放
    func scaleImage(scaleSize:CGFloat,image:UIImage)->UIImage {
        let reSize = CGSize.init(width: image.size.width * scaleSize, height: image.size.height * scaleSize)
        return self.reSizeImage(reSize: reSize, image: image)
    }
    
    // 将十六进制转为rgb
    func colorConversion(Color_Value:NSString, alpha: CGFloat)->(R:CGFloat,G:CGFloat,B:CGFloat){
        var Str:NSString = Color_Value.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines).uppercased() as NSString
        if Color_Value.hasPrefix("#"){
            Str=(Color_Value as NSString).substring(from: 1) as NSString
        }
        let redStr = (Str as NSString ).substring(to: 2)
        let greenStr = ((Str as NSString).substring(from: 2) as NSString).substring(to: 2)
        let blueStr = ((Str as NSString).substring(from: 4) as NSString).substring(to: 2)
        var r:UInt64 = 0, g:UInt64 = 0, b:UInt64 = 0;
        Scanner(string: redStr).scanHexInt64(&r)
        Scanner(string: greenStr).scanHexInt64(&g)
        Scanner(string: blueStr).scanHexInt64(&b)
        return (CGFloat(r),CGFloat(g),CGFloat(b))
    }
    
    // 将图片转为固定字节大小的图片
    func resetImgSize(sourceImage : UIImage,maxImageLenght : CGFloat,maxSizeKB : CGFloat) -> Data {
        
        var maxSize = maxSizeKB
        var maxImageSize = maxImageLenght
        if (maxSize <= 0.0) {
            maxSize = 1024.0;
        }
        if (maxImageSize <= 0.0)  {
            maxImageSize = 1024.0;
        }
        
        //先调整分辨率
        var newSize = CGSize.init(width: sourceImage.size.width, height: sourceImage.size.height)
        let tempHeight = newSize.height / maxImageSize;
        let tempWidth = newSize.width / maxImageSize;
        if (tempWidth > 1.0 && tempWidth > tempHeight) {
            newSize = CGSize.init(width: sourceImage.size.width / tempWidth, height: sourceImage.size.height / tempWidth)
        }
        else if (tempHeight > 1.0 && tempWidth < tempHeight){
            newSize = CGSize.init(width: sourceImage.size.width / tempHeight, height: sourceImage.size.height / tempHeight)
        }
        UIGraphicsBeginImageContext(newSize)
        sourceImage.draw(in: CGRect.init(x: 0, y: 0, width: newSize.width, height: newSize.height))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        var imageData = newImage!.jpegData(compressionQuality: 1.0)
        var sizeOriginKB : CGFloat = CGFloat((imageData?.count)!) / 1024.0;
        //调整大小
        var resizeRate = 0.9;
        while (sizeOriginKB > maxSize && resizeRate > 0.1) {
            imageData = newImage!.jpegData(compressionQuality: CGFloat(resizeRate))
            sizeOriginKB = CGFloat((imageData?.count)!) / 1024.0;
            resizeRate -= 0.1;
        }
        return imageData!
    }
    
    //时间转为时间戳
    func stringToTimeStamp(stringTime:NSString,format:NSString)->NSString
    {
        if stringTime.isEqual(to: "") {
            return ""
        }
        
        let dfmatter = DateFormatter()
        dfmatter.dateFormat = format as String?
        if format == "" {
            dfmatter.dateFormat = "YYYY-MM-dd HH:mm:ss"
        }
        let date = dfmatter.date(from: stringTime as String)
        let dateStamp:TimeInterval = date!.timeIntervalSince1970
        let dateSt:String = String(dateStamp)
        return dateSt as NSString
    }
    
    //时间戳转换为时间
    func timeStampToTime(timeStamp:Double,format:String) ->String
    {
        if timeStamp == 0 {
            return ""
        }
        //转换为时间
        let timeInterval:TimeInterval = TimeInterval(timeStamp / 1000)
        let date = Date(timeIntervalSince1970: timeInterval)
        
        //格式化输出
        let dformatter = DateFormatter()
        dformatter.dateFormat = format as String?
        if format == "" {
            dformatter.dateFormat = "YYYY-MM-dd HH:mm:ss"
        }
        return dformatter.string(from: date)
    }
    
    //从SB创建VX
    func getVCFromSB(identifier:String) -> UIViewController {
        
        var vc:UIViewController?
        
        if Bundle.main.path(forResource: "Base.lproj/Main.storyboardc/"+identifier, ofType: "nib") != nil{
            vc =  UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: identifier)
        }else{
            vc = getVCFromClassName(className: identifier)
        }
        return vc!
    }
    
    //类名创建VC
    func getVCFromClassName(className: String) -> UIViewController {
        
        let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String;
        
        let cls = NSClassFromString("\(namespace).\(className)")! as! UIViewController.Type
        
        let vc = cls.init()
        
        return vc;
    }
    
    func getFirstImgFromUrl(url: String, completion: @escaping (_ img: UIImage?) -> Void) {
        let itemPath: AVURLAsset = AVURLAsset.init(url: NSURL.init(string: url)! as URL)
        //获取视频第一帧图片
        let gen = AVAssetImageGenerator.init(asset: itemPath)
        gen.appliesPreferredTrackTransform = true
        let time = CMTimeMakeWithSeconds(0.0, preferredTimescale: 1)
        var actualTime : CMTime = CMTimeMakeWithSeconds(0, preferredTimescale: 0)
        do {
            let imageCg = try gen.copyCGImage(at: time, actualTime: &actualTime)
            let image = UIImage.init(cgImage: imageCg)
            
            completion(image)
            
        } catch  {
            print("视频尺寸获取失败")
            completion(nil)
        }
    }
    
    //判断是否纯数字
    func isPureInt(text:String) -> Bool {
        let scan = Scanner.init(string: text)
        var  val:Int = 0;
        return scan.scanInt(&val) && scan.isAtEnd
    }
    
    //验证是否数字+大小写字母
    func isNumberAndLetter(text:String) -> Bool {
        let regex = "^[A-Za-z0-9]{0,}$"
        let pred = NSPredicate.init(format: "SELF MATCHES %@", regex)
        return pred.evaluate(with: text)
    }
    
    //11位手机号码
    func is11Phone(text:String) -> Bool {
        let regex = "^1[0-9]{10}$"
        let pred = NSPredicate.init(format: "SELF MATCHES %@", regex)
        return pred.evaluate(with: text)
    }
    
    //获取当前Vc
    func getCurrentVc(baseViewController: UIViewController? = nil) -> UIViewController {
        var base: UIViewController? = baseViewController
        if (base == nil) {
            base = getRootVc()
        }
        
        if let nav = base as? UINavigationController {
            return getCurrentVc(baseViewController: nav.visibleViewController)
        }
        if let tab = base as? UITabBarController {
            return getCurrentVc(baseViewController: tab.selectedViewController)
        }
        if let presented = base?.presentedViewController {
            return getCurrentVc(baseViewController: presented)
        }
        return base!
    }
    func getCurrentVc(vc:UIViewController) -> UIViewController {
        if vc is UINavigationController{
            return getCurrentVc(vc:getCurrentVc())
        }
        
        var topVC = getRootVc()
        while topVC.presentedViewController != nil {
            topVC = topVC.presentedViewController!
        }
        return topVC
        
    }
    //获取秒
    func getCurrentTimeSec() -> Int {
        //获取当前时间
        let now = NSDate()
        //当前时间的时间戳
        let timeInterval:TimeInterval = now.timeIntervalSince1970
        let timeStamp = Int(timeInterval)
        return timeStamp
    }
    // 定位权限
    func checkLocationAuthority() {
        let manager = CLLocationManager()
        let authorizationStatus: CLAuthorizationStatus

        if #available(iOS 14, *) {
            authorizationStatus = manager.authorizationStatus
        } else {
            authorizationStatus = CLLocationManager.authorizationStatus()
        }
        
        if authorizationStatus == .denied  {

            let alertController = UIAlertController(title: "打开定位开关", message: "定位服务未开启,请进入系统设置>隐私>定位服务中打开开关,并允许家巴啦云视使用定位服务", preferredStyle: .alert)
            let cancelAction = UIAlertAction(title: "取消", style: .cancel, handler: nil)
            let okAction = UIAlertAction(title: "立即设置", style: .default, handler:
            {
                action in

                let url = NSURL.init(string: UIApplication.openSettingsURLString)
                if #available(iOS 10.0, *) {
                    UIApplication.shared.open(url! as URL, options: [:], completionHandler: nil)
                } else {
                    // Fallback on earlier versions
                    UIApplication.shared.openURL(url! as URL)
                }
            })
            alertController.addAction(cancelAction)
            alertController.addAction(okAction)
            UtilManager.sharedInstance.getCurrentVc().present(alertController, animated: true, completion: nil)
        }
    }
    //生成图片
    func imageFromView(view:UIView,suggest_min_px_short:CGFloat) -> UIImage? {
        
        var scale = suggest_min_px_short/view.frame.height
        
        if(view.frame.size.width>view.frame.size.height){
            //横向的话，用短边跟高度比
            scale = suggest_min_px_short/view.frame.size.height
        }else{
            scale = suggest_min_px_short/view.frame.size.width
        }
        
        UIGraphicsBeginImageContextWithOptions(CGSize.init(width:view.bounds.size.width - 1.0/scale, height: view.bounds.size.height - 1.0/scale), view.isOpaque, scale)
        view.layer.render(in: UIGraphicsGetCurrentContext()!)
        let img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return img
        
    }
    // JSONString转换为字典
    func getDictionaryFromJSONString(jsonString:String) ->NSDictionary{
        
        let jsonData:Data = jsonString.data(using: .utf8)!
        
        let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
        if dict != nil {
            return dict as! NSDictionary
        }
        return NSDictionary()
    }
    //JSONString转换为数组
    func getArrayFromJSONString(jsonString:String) ->NSArray{
        let jsonData:Data = jsonString.data(using: .utf8)!
        
        let array = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
        if array != nil {
            return array as! NSArray
        }
        return array as! NSArray
    }
    
    //字典转换为JSONString
    func getJSONStringFromDictionary(dictionary:NSDictionary) -> String {
        if (!JSONSerialization.isValidJSONObject(dictionary)) {
            print("无法解析出JSONString")
            return ""
        }
        let data : NSData! = try? JSONSerialization.data(withJSONObject: dictionary, options: []) as NSData
        let JSONString = NSString(data:data as Data,encoding: String.Encoding.utf8.rawValue)
        return JSONString! as String
    }
    //数组转json
    func getJSONStringFromArray(array:NSArray) -> String {
        if (!JSONSerialization.isValidJSONObject(array)) {
            print("无法解析出JSONString")
            return ""
        }
        
        let data : NSData! = try? JSONSerialization.data(withJSONObject: array, options: []) as NSData
        let JSONString = NSString(data:data as Data,encoding: String.Encoding.utf8.rawValue)
        return JSONString! as String
    }
    
    // MARK: - 降低质量,生成指定大小的图片
    func resetSizeOfImageData(source_image: UIImage!, maxSize: Int) -> NSData {
        //先判断当前质量是否满足要求，不满足再进行压缩
        var finallImageData = source_image.jpegData(compressionQuality: 1.0)
        let sizeOrigin      = finallImageData?.count
        let sizeOriginKB    = sizeOrigin! / 1024
        if sizeOriginKB <= maxSize {
            return finallImageData! as NSData
        }
        
        //先调整分辨率
        var defaultSize = CGSize(width: 1024, height: 1024)
        let newImage = self.newSizeImage(size: defaultSize, source_image: source_image)
        
        finallImageData = newImage.jpegData(compressionQuality: 1.0);
        
        //保存压缩系数
        let compressionQualityArr = NSMutableArray()
        let avg = CGFloat(1.0/250)
        var value = avg
        
        var i = 250
        repeat {
            i -= 1
            value = CGFloat(i)*avg
            compressionQualityArr.add(value)
        } while i >= 1

        
        /*
         调整大小
         说明：压缩系数数组compressionQualityArr是从大到小存储。
         */
        //思路：使用二分法搜索
        finallImageData = self.halfFuntion(arr: compressionQualityArr.copy() as! [CGFloat], image: newImage, sourceData: finallImageData!, maxSize: maxSize)
        //如果还是未能压缩到指定大小，则进行降分辨率
        while finallImageData?.count == 0 {
            //每次降100分辨率
            if defaultSize.width-100 <= 0 || defaultSize.height-100 <= 0 {
                break
            }
            defaultSize = CGSize(width: defaultSize.width-100, height: defaultSize.height-100)
            let image = self.newSizeImage(size: defaultSize, source_image: UIImage.init(data: newImage.jpegData(compressionQuality: compressionQualityArr.lastObject as! CGFloat)!)!)
            finallImageData = self.halfFuntion(arr: compressionQualityArr.copy() as! [CGFloat], image: image, sourceData: image.jpegData(compressionQuality: 1.0)!, maxSize: maxSize)
        }
        
        return finallImageData! as NSData
    }

    // MARK: - 调整图片分辨率/尺寸（等比例缩放）
    func newSizeImage(size: CGSize, source_image: UIImage) -> UIImage {
        var newSize = CGSize(width: source_image.size.width, height: source_image.size.height)
        let tempHeight = newSize.height / size.height
        let tempWidth = newSize.width / size.width
        
        if tempWidth > 1.0 && tempWidth > tempHeight {
            newSize = CGSize(width: source_image.size.width / tempWidth, height: source_image.size.height / tempWidth)
        } else if tempHeight > 1.0 && tempWidth < tempHeight {
            newSize = CGSize(width: source_image.size.width / tempHeight, height: source_image.size.height / tempHeight)
        }
        
        UIGraphicsBeginImageContext(newSize)
        source_image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }

    // MARK: - 二分法
    func halfFuntion(arr: [CGFloat], image: UIImage, sourceData finallImageData: Data, maxSize: Int) -> Data? {
        var tempFinallImageData = finallImageData
        
        var tempData = Data.init()
        var start = 0
        var end = arr.count - 1
        var index = 0
        
        var difference = Int.max
        while start <= end {
            index = start + (end - start)/2
            
            tempFinallImageData = image.jpegData(compressionQuality: arr[index])!
            
            let sizeOrigin = tempFinallImageData.count
            let sizeOriginKB = sizeOrigin / 1024
            
            print("当前降到的质量：\(sizeOriginKB)\n\(index)----\(arr[index])")
            
            if sizeOriginKB > maxSize {
                start = index + 1
            } else if sizeOriginKB < maxSize {
                if maxSize-sizeOriginKB < difference {
                    difference = maxSize-sizeOriginKB
                    tempData = tempFinallImageData
                }
                if index<=0 {
                    break
                }
                end = index - 1
            } else {
                break
            }
        }
        return tempData
    }
    
    func getHud(view:UIView,show:Bool) -> MBProgressHUD {
        let hud = MBProgressHUD.init(view: view)
        hud.removeFromSuperViewOnHide = true
        view.addSubview(hud)
        hud.graceTime = 0.3
        if(show){
            hud.show(animated: true)
        }
        return hud
    }
    
    func showHud(text: String? = nil) {
        let hud = MBProgressHUD.showAdded(to: getCurrentVc().view, animated: true)
        hud.mode = .indeterminate
        if let title = text {
            hud.label.text = title
        }
    }
    
    func hideHud() {
        DispatchQueue.main.asyncAfter(deadline: .now()) {
            MBProgressHUD.hide(for: self.getCurrentVc().view, animated: true)
        }
    }
    
    //摄像头权限
    func cameraPermissions() -> Bool{
        let authStatus:AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
        
        if(authStatus == AVAuthorizationStatus.denied || authStatus == AVAuthorizationStatus.restricted) {
            return false
        }else {
            return true
        }
    }
    
    //相册权限
    func photoLibraryPermissions() -> Bool {
        let library:PHAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
        if(library == PHAuthorizationStatus.denied || library == PHAuthorizationStatus.restricted){
            return false
        }else {
            return true
        }
    }
    
    //获取url参数
    func getQueryStringParameter(url: String, param: String) -> String? {
        guard let url = URLComponents(string: url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!) else { return nil }
        return url.queryItems?.first(where: { $0.name == param })?.value
    }
    
    // 密码验证
    func judgePassWordLegal(_ pass: String?) -> Bool {
        var result: Bool
        // 判断长度大于6位小于16位后再接着判断是否同时包含数字和大小写字母
        let regex = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$"
        let pred = NSPredicate(format: "SELF MATCHES %@", regex)
        result = pred.evaluate(with: pass)
        print(String(format: "%hhd", result))
        return result
    }
    
    
}

//扩展mbprogressHud
extension MBProgressHUD{
    func hideHud(delay:Double,onlyText:Bool) -> () {
        if delay == 0{
            self.hide(animated: true)
        }else{
            if onlyText{
                
                self.mode = MBProgressHUDMode.text
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
                self.hide(animated: true)
            }
        }
    }
}

//扩展各种数字转换
extension Int {
    var cgf: CGFloat { return CGFloat(self) }
    var f: Float { return Float(self) }
    var str: String { return String(format: "%d", Int(self)) }
}

extension Float {
    var cgf: CGFloat {
        return CGFloat(self)
    }
    
    func str(size:Int) -> String {
        let x = CGFloat(self)
        let s = String(format: "%.\(size)f", Double(x))
        return s
    }
}

extension Double {
    var cgf: CGFloat { return CGFloat(self) }
    var f: Float { return Float(self) }
    var i: Int {return Int(self)}
    
}

extension CGFloat {
    var f :Float{
        return Float(self)
    }
    func str(size:Int) -> String {
        let x = CGFloat(self)
        let s = String(format: "%.\(size)f", Double(x))
        return s
    }
    //var str: String { return String(format: "%.8f", Double(self)) }
}

extension String {
    var f :Float{
        if Float(self) == nil{
            return 0.0
        }else{
            return Float(self)!
            
        }
        
    }
    var i :Int{
        if Int(self) == nil{
            return 0
        }else{
            return Int(self)!
            
        }
    }
    
}

extension UIScrollView {
   func scrollToBottom(animated: Bool) {
     if self.contentSize.height < self.bounds.size.height { return }
     let bottomOffset = CGPoint(x: 0, y: self.contentSize.height - self.bounds.size.height)
     self.setContentOffset(bottomOffset, animated: animated)
  }
}










